// Parliament is licensed under the BSD License from the Open Source
// Initiative, http://www.opensource.org/licenses/bsd-license.php
//
// Copyright (c) 2001-2009, BBN Technologies, Inc.
// All rights reserved.

#include <boost/test/unit_test.hpp>
#include <boost/test/data/monomorphic.hpp>
#include <boost/test/data/test_case.hpp>
#include <iterator>
#include <list>
#include <ostream>
#include <string>
#include "parliament/UnicodeIterator.h"

namespace bdata = ::boost::unit_test::data;

using namespace ::bbn::parliament;
using ::std::char_traits;
using ::std::list;
using ::std::nothrow;
using ::std::ostream;
using ::std::string;

struct TestCase
{
	const char*			m_pUtf8Input;
	const Utf16Char*	m_pUtf16Input;
	const uint32*		m_pExpectedResult;
};

// Required to make BOOST_DATA_TEST_CASE happy:
static ostream& operator<<(ostream& os, const TestCase& tc)
{
	os << tc.m_pUtf8Input << ::std::endl;
	return os;
}

////////////// Generated by UnicodeTestCaseGen.cpp -- Begin //////////////

// ﻿VMWаX二Y𐌂Z
static const char k_testCase00Utf8Input[] =
	{ '\xef', '\xbb', '\xbf', '\x56', '\x4d', '\x57', '\xd0', '\xb0', '\x58', '\xe4',
		'\xba', '\x8c', '\x59', '\xf0', '\x90', '\x8c', '\x82', '\x5a', '\x00' };
static const Utf16Char k_testCase00Utf16Input[] =
	{ 0xfeff, 0x0056, 0x004d, 0x0057, 0x0430, 0x0058, 0x4e8c, 0x0059, 0xd800, 0xdf02,
		0x005a, 0x0000 };
static const Utf32Char k_testCase00ExpectedResult[] =
	{ 0x000056, 0x00004d, 0x000057, 0x000430, 0x000058, 0x004e8c, 0x000059, 0x010302,
		0x00005a, 0x000000 };

// VMWаX二Y𐌂Z
static const char k_testCase01Utf8Input[] =
	{ '\x56', '\x4d', '\x57', '\xd0', '\xb0', '\x58', '\xe4', '\xba', '\x8c', '\x59',
		'\xf0', '\x90', '\x8c', '\x82', '\x5a', '\x00' };
static const Utf16Char k_testCase01Utf16Input[] =
	{ 0x0056, 0x004d, 0x0057, 0x0430, 0x0058, 0x4e8c, 0x0059, 0xd800, 0xdf02, 0x005a, 0x0000 };
static const Utf32Char k_testCase01ExpectedResult[] =
	{ 0x000056, 0x00004d, 0x000057, 0x000430, 0x000058, 0x004e8c, 0x000059, 0x010302,
		0x00005a, 0x000000 };

// English:  Leading the Web to its Full Potential…
static const char k_testCase02Utf8Input[] =
	{ '\x45', '\x6e', '\x67', '\x6c', '\x69', '\x73', '\x68', '\x3a', '\x20', '\x20',
		'\x4c', '\x65', '\x61', '\x64', '\x69', '\x6e', '\x67', '\x20', '\x74', '\x68',
		'\x65', '\x20', '\x57', '\x65', '\x62', '\x20', '\x74', '\x6f', '\x20', '\x69',
		'\x74', '\x73', '\x20', '\x46', '\x75', '\x6c', '\x6c', '\x20', '\x50', '\x6f',
		'\x74', '\x65', '\x6e', '\x74', '\x69', '\x61', '\x6c', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase02Utf16Input[] =
	{ 0x0045, 0x006e, 0x0067, 0x006c, 0x0069, 0x0073, 0x0068, 0x003a, 0x0020, 0x0020,
		0x004c, 0x0065, 0x0061, 0x0064, 0x0069, 0x006e, 0x0067, 0x0020, 0x0074, 0x0068,
		0x0065, 0x0020, 0x0057, 0x0065, 0x0062, 0x0020, 0x0074, 0x006f, 0x0020, 0x0069,
		0x0074, 0x0073, 0x0020, 0x0046, 0x0075, 0x006c, 0x006c, 0x0020, 0x0050, 0x006f,
		0x0074, 0x0065, 0x006e, 0x0074, 0x0069, 0x0061, 0x006c, 0x2026, 0x0000 };
static const Utf32Char k_testCase02ExpectedResult[] =
	{ 0x000045, 0x00006e, 0x000067, 0x00006c, 0x000069, 0x000073, 0x000068, 0x00003a,
		0x000020, 0x000020, 0x00004c, 0x000065, 0x000061, 0x000064, 0x000069, 0x00006e,
		0x000067, 0x000020, 0x000074, 0x000068, 0x000065, 0x000020, 0x000057, 0x000065,
		0x000062, 0x000020, 0x000074, 0x00006f, 0x000020, 0x000069, 0x000074, 0x000073,
		0x000020, 0x000046, 0x000075, 0x00006c, 0x00006c, 0x000020, 0x000050, 0x00006f,
		0x000074, 0x000065, 0x00006e, 0x000074, 0x000069, 0x000061, 0x00006c, 0x002026, 0x000000 };

// Catalan:  Duent la Web al seu ple potencial…
static const char k_testCase03Utf8Input[] =
	{ '\x43', '\x61', '\x74', '\x61', '\x6c', '\x61', '\x6e', '\x3a', '\x20', '\x20',
		'\x44', '\x75', '\x65', '\x6e', '\x74', '\x20', '\x6c', '\x61', '\x20', '\x57',
		'\x65', '\x62', '\x20', '\x61', '\x6c', '\x20', '\x73', '\x65', '\x75', '\x20',
		'\x70', '\x6c', '\x65', '\x20', '\x70', '\x6f', '\x74', '\x65', '\x6e', '\x63',
		'\x69', '\x61', '\x6c', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase03Utf16Input[] =
	{ 0x0043, 0x0061, 0x0074, 0x0061, 0x006c, 0x0061, 0x006e, 0x003a, 0x0020, 0x0020,
		0x0044, 0x0075, 0x0065, 0x006e, 0x0074, 0x0020, 0x006c, 0x0061, 0x0020, 0x0057,
		0x0065, 0x0062, 0x0020, 0x0061, 0x006c, 0x0020, 0x0073, 0x0065, 0x0075, 0x0020,
		0x0070, 0x006c, 0x0065, 0x0020, 0x0070, 0x006f, 0x0074, 0x0065, 0x006e, 0x0063,
		0x0069, 0x0061, 0x006c, 0x2026, 0x0000 };
static const Utf32Char k_testCase03ExpectedResult[] =
	{ 0x000043, 0x000061, 0x000074, 0x000061, 0x00006c, 0x000061, 0x00006e, 0x00003a,
		0x000020, 0x000020, 0x000044, 0x000075, 0x000065, 0x00006e, 0x000074, 0x000020,
		0x00006c, 0x000061, 0x000020, 0x000057, 0x000065, 0x000062, 0x000020, 0x000061,
		0x00006c, 0x000020, 0x000073, 0x000065, 0x000075, 0x000020, 0x000070, 0x00006c,
		0x000065, 0x000020, 0x000070, 0x00006f, 0x000074, 0x000065, 0x00006e, 0x000063,
		0x000069, 0x000061, 0x00006c, 0x002026, 0x000000 };

// Dutch:  Het Web tot zijn volle potentieel ontwikkelen…
static const char k_testCase04Utf8Input[] =
	{ '\x44', '\x75', '\x74', '\x63', '\x68', '\x3a', '\x20', '\x20', '\x48', '\x65',
		'\x74', '\x20', '\x57', '\x65', '\x62', '\x20', '\x74', '\x6f', '\x74', '\x20',
		'\x7a', '\x69', '\x6a', '\x6e', '\x20', '\x76', '\x6f', '\x6c', '\x6c', '\x65',
		'\x20', '\x70', '\x6f', '\x74', '\x65', '\x6e', '\x74', '\x69', '\x65', '\x65',
		'\x6c', '\x20', '\x6f', '\x6e', '\x74', '\x77', '\x69', '\x6b', '\x6b', '\x65',
		'\x6c', '\x65', '\x6e', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase04Utf16Input[] =
	{ 0x0044, 0x0075, 0x0074, 0x0063, 0x0068, 0x003a, 0x0020, 0x0020, 0x0048, 0x0065,
		0x0074, 0x0020, 0x0057, 0x0065, 0x0062, 0x0020, 0x0074, 0x006f, 0x0074, 0x0020,
		0x007a, 0x0069, 0x006a, 0x006e, 0x0020, 0x0076, 0x006f, 0x006c, 0x006c, 0x0065,
		0x0020, 0x0070, 0x006f, 0x0074, 0x0065, 0x006e, 0x0074, 0x0069, 0x0065, 0x0065,
		0x006c, 0x0020, 0x006f, 0x006e, 0x0074, 0x0077, 0x0069, 0x006b, 0x006b, 0x0065,
		0x006c, 0x0065, 0x006e, 0x2026, 0x0000 };
static const Utf32Char k_testCase04ExpectedResult[] =
	{ 0x000044, 0x000075, 0x000074, 0x000063, 0x000068, 0x00003a, 0x000020, 0x000020,
		0x000048, 0x000065, 0x000074, 0x000020, 0x000057, 0x000065, 0x000062, 0x000020,
		0x000074, 0x00006f, 0x000074, 0x000020, 0x00007a, 0x000069, 0x00006a, 0x00006e,
		0x000020, 0x000076, 0x00006f, 0x00006c, 0x00006c, 0x000065, 0x000020, 0x000070,
		0x00006f, 0x000074, 0x000065, 0x00006e, 0x000074, 0x000069, 0x000065, 0x000065,
		0x00006c, 0x000020, 0x00006f, 0x00006e, 0x000074, 0x000077, 0x000069, 0x00006b,
		0x00006b, 0x000065, 0x00006c, 0x000065, 0x00006e, 0x002026, 0x000000 };

// French:  Amener le Web vers son plein potentiel…
static const char k_testCase05Utf8Input[] =
	{ '\x46', '\x72', '\x65', '\x6e', '\x63', '\x68', '\x3a', '\x20', '\x20', '\x41',
		'\x6d', '\x65', '\x6e', '\x65', '\x72', '\x20', '\x6c', '\x65', '\x20', '\x57',
		'\x65', '\x62', '\x20', '\x76', '\x65', '\x72', '\x73', '\x20', '\x73', '\x6f',
		'\x6e', '\x20', '\x70', '\x6c', '\x65', '\x69', '\x6e', '\x20', '\x70', '\x6f',
		'\x74', '\x65', '\x6e', '\x74', '\x69', '\x65', '\x6c', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase05Utf16Input[] =
	{ 0x0046, 0x0072, 0x0065, 0x006e, 0x0063, 0x0068, 0x003a, 0x0020, 0x0020, 0x0041,
		0x006d, 0x0065, 0x006e, 0x0065, 0x0072, 0x0020, 0x006c, 0x0065, 0x0020, 0x0057,
		0x0065, 0x0062, 0x0020, 0x0076, 0x0065, 0x0072, 0x0073, 0x0020, 0x0073, 0x006f,
		0x006e, 0x0020, 0x0070, 0x006c, 0x0065, 0x0069, 0x006e, 0x0020, 0x0070, 0x006f,
		0x0074, 0x0065, 0x006e, 0x0074, 0x0069, 0x0065, 0x006c, 0x2026, 0x0000 };
static const Utf32Char k_testCase05ExpectedResult[] =
	{ 0x000046, 0x000072, 0x000065, 0x00006e, 0x000063, 0x000068, 0x00003a, 0x000020,
		0x000020, 0x000041, 0x00006d, 0x000065, 0x00006e, 0x000065, 0x000072, 0x000020,
		0x00006c, 0x000065, 0x000020, 0x000057, 0x000065, 0x000062, 0x000020, 0x000076,
		0x000065, 0x000072, 0x000073, 0x000020, 0x000073, 0x00006f, 0x00006e, 0x000020,
		0x000070, 0x00006c, 0x000065, 0x000069, 0x00006e, 0x000020, 0x000070, 0x00006f,
		0x000074, 0x000065, 0x00006e, 0x000074, 0x000069, 0x000065, 0x00006c, 0x002026, 0x000000 };

// German:  Alle Möglichkeiten des Web erschließen…
static const char k_testCase06Utf8Input[] =
	{ '\x47', '\x65', '\x72', '\x6d', '\x61', '\x6e', '\x3a', '\x20', '\x20', '\x41',
		'\x6c', '\x6c', '\x65', '\x20', '\x4d', '\xc3', '\xb6', '\x67', '\x6c', '\x69',
		'\x63', '\x68', '\x6b', '\x65', '\x69', '\x74', '\x65', '\x6e', '\x20', '\x64',
		'\x65', '\x73', '\x20', '\x57', '\x65', '\x62', '\x20', '\x65', '\x72', '\x73',
		'\x63', '\x68', '\x6c', '\x69', '\x65', '\xc3', '\x9f', '\x65', '\x6e', '\xe2',
		'\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase06Utf16Input[] =
	{ 0x0047, 0x0065, 0x0072, 0x006d, 0x0061, 0x006e, 0x003a, 0x0020, 0x0020, 0x0041,
		0x006c, 0x006c, 0x0065, 0x0020, 0x004d, 0x00f6, 0x0067, 0x006c, 0x0069, 0x0063,
		0x0068, 0x006b, 0x0065, 0x0069, 0x0074, 0x0065, 0x006e, 0x0020, 0x0064, 0x0065,
		0x0073, 0x0020, 0x0057, 0x0065, 0x0062, 0x0020, 0x0065, 0x0072, 0x0073, 0x0063,
		0x0068, 0x006c, 0x0069, 0x0065, 0x00df, 0x0065, 0x006e, 0x2026, 0x0000 };
static const Utf32Char k_testCase06ExpectedResult[] =
	{ 0x000047, 0x000065, 0x000072, 0x00006d, 0x000061, 0x00006e, 0x00003a, 0x000020,
		0x000020, 0x000041, 0x00006c, 0x00006c, 0x000065, 0x000020, 0x00004d, 0x0000f6,
		0x000067, 0x00006c, 0x000069, 0x000063, 0x000068, 0x00006b, 0x000065, 0x000069,
		0x000074, 0x000065, 0x00006e, 0x000020, 0x000064, 0x000065, 0x000073, 0x000020,
		0x000057, 0x000065, 0x000062, 0x000020, 0x000065, 0x000072, 0x000073, 0x000063,
		0x000068, 0x00006c, 0x000069, 0x000065, 0x0000df, 0x000065, 0x00006e, 0x002026, 0x000000 };

// Greek:  Οδηγώντας τον παγκόμιο ιστό στο μέγιστο των δυνατοτήτων του…
static const char k_testCase07Utf8Input[] =
	{ '\x47', '\x72', '\x65', '\x65', '\x6b', '\x3a', '\x20', '\x20', '\xce', '\x9f',
		'\xce', '\xb4', '\xce', '\xb7', '\xce', '\xb3', '\xcf', '\x8e', '\xce', '\xbd',
		'\xcf', '\x84', '\xce', '\xb1', '\xcf', '\x82', '\x20', '\xcf', '\x84', '\xce',
		'\xbf', '\xce', '\xbd', '\x20', '\xcf', '\x80', '\xce', '\xb1', '\xce', '\xb3',
		'\xce', '\xba', '\xcf', '\x8c', '\xce', '\xbc', '\xce', '\xb9', '\xce', '\xbf',
		'\x20', '\xce', '\xb9', '\xcf', '\x83', '\xcf', '\x84', '\xcf', '\x8c', '\x20',
		'\xcf', '\x83', '\xcf', '\x84', '\xce', '\xbf', '\x20', '\xce', '\xbc', '\xce',
		'\xad', '\xce', '\xb3', '\xce', '\xb9', '\xcf', '\x83', '\xcf', '\x84', '\xce',
		'\xbf', '\x20', '\xcf', '\x84', '\xcf', '\x89', '\xce', '\xbd', '\x20', '\xce',
		'\xb4', '\xcf', '\x85', '\xce', '\xbd', '\xce', '\xb1', '\xcf', '\x84', '\xce',
		'\xbf', '\xcf', '\x84', '\xce', '\xae', '\xcf', '\x84', '\xcf', '\x89', '\xce',
		'\xbd', '\x20', '\xcf', '\x84', '\xce', '\xbf', '\xcf', '\x85', '\xe2', '\x80',
		'\xa6', '\x00' };
static const Utf16Char k_testCase07Utf16Input[] =
	{ 0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x003a, 0x0020, 0x0020, 0x039f, 0x03b4,
		0x03b7, 0x03b3, 0x03ce, 0x03bd, 0x03c4, 0x03b1, 0x03c2, 0x0020, 0x03c4, 0x03bf,
		0x03bd, 0x0020, 0x03c0, 0x03b1, 0x03b3, 0x03ba, 0x03cc, 0x03bc, 0x03b9, 0x03bf,
		0x0020, 0x03b9, 0x03c3, 0x03c4, 0x03cc, 0x0020, 0x03c3, 0x03c4, 0x03bf, 0x0020,
		0x03bc, 0x03ad, 0x03b3, 0x03b9, 0x03c3, 0x03c4, 0x03bf, 0x0020, 0x03c4, 0x03c9,
		0x03bd, 0x0020, 0x03b4, 0x03c5, 0x03bd, 0x03b1, 0x03c4, 0x03bf, 0x03c4, 0x03ae,
		0x03c4, 0x03c9, 0x03bd, 0x0020, 0x03c4, 0x03bf, 0x03c5, 0x2026, 0x0000 };
static const Utf32Char k_testCase07ExpectedResult[] =
	{ 0x000047, 0x000072, 0x000065, 0x000065, 0x00006b, 0x00003a, 0x000020, 0x000020,
		0x00039f, 0x0003b4, 0x0003b7, 0x0003b3, 0x0003ce, 0x0003bd, 0x0003c4, 0x0003b1,
		0x0003c2, 0x000020, 0x0003c4, 0x0003bf, 0x0003bd, 0x000020, 0x0003c0, 0x0003b1,
		0x0003b3, 0x0003ba, 0x0003cc, 0x0003bc, 0x0003b9, 0x0003bf, 0x000020, 0x0003b9,
		0x0003c3, 0x0003c4, 0x0003cc, 0x000020, 0x0003c3, 0x0003c4, 0x0003bf, 0x000020,
		0x0003bc, 0x0003ad, 0x0003b3, 0x0003b9, 0x0003c3, 0x0003c4, 0x0003bf, 0x000020,
		0x0003c4, 0x0003c9, 0x0003bd, 0x000020, 0x0003b4, 0x0003c5, 0x0003bd, 0x0003b1,
		0x0003c4, 0x0003bf, 0x0003c4, 0x0003ae, 0x0003c4, 0x0003c9, 0x0003bd, 0x000020,
		0x0003c4, 0x0003bf, 0x0003c5, 0x002026, 0x000000 };

// Hungarian:  Hogy kihasználhassuk a Web nyújtotta összes lehetőséget…
static const char k_testCase08Utf8Input[] =
	{ '\x48', '\x75', '\x6e', '\x67', '\x61', '\x72', '\x69', '\x61', '\x6e', '\x3a',
		'\x20', '\x20', '\x48', '\x6f', '\x67', '\x79', '\x20', '\x6b', '\x69', '\x68',
		'\x61', '\x73', '\x7a', '\x6e', '\xc3', '\xa1', '\x6c', '\x68', '\x61', '\x73',
		'\x73', '\x75', '\x6b', '\x20', '\x61', '\x20', '\x57', '\x65', '\x62', '\x20',
		'\x6e', '\x79', '\xc3', '\xba', '\x6a', '\x74', '\x6f', '\x74', '\x74', '\x61',
		'\x20', '\xc3', '\xb6', '\x73', '\x73', '\x7a', '\x65', '\x73', '\x20', '\x6c',
		'\x65', '\x68', '\x65', '\x74', '\xc5', '\x91', '\x73', '\xc3', '\xa9', '\x67',
		'\x65', '\x74', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase08Utf16Input[] =
	{ 0x0048, 0x0075, 0x006e, 0x0067, 0x0061, 0x0072, 0x0069, 0x0061, 0x006e, 0x003a,
		0x0020, 0x0020, 0x0048, 0x006f, 0x0067, 0x0079, 0x0020, 0x006b, 0x0069, 0x0068,
		0x0061, 0x0073, 0x007a, 0x006e, 0x00e1, 0x006c, 0x0068, 0x0061, 0x0073, 0x0073,
		0x0075, 0x006b, 0x0020, 0x0061, 0x0020, 0x0057, 0x0065, 0x0062, 0x0020, 0x006e,
		0x0079, 0x00fa, 0x006a, 0x0074, 0x006f, 0x0074, 0x0074, 0x0061, 0x0020, 0x00f6,
		0x0073, 0x0073, 0x007a, 0x0065, 0x0073, 0x0020, 0x006c, 0x0065, 0x0068, 0x0065,
		0x0074, 0x0151, 0x0073, 0x00e9, 0x0067, 0x0065, 0x0074, 0x2026, 0x0000 };
static const Utf32Char k_testCase08ExpectedResult[] =
	{ 0x000048, 0x000075, 0x00006e, 0x000067, 0x000061, 0x000072, 0x000069, 0x000061,
		0x00006e, 0x00003a, 0x000020, 0x000020, 0x000048, 0x00006f, 0x000067, 0x000079,
		0x000020, 0x00006b, 0x000069, 0x000068, 0x000061, 0x000073, 0x00007a, 0x00006e,
		0x0000e1, 0x00006c, 0x000068, 0x000061, 0x000073, 0x000073, 0x000075, 0x00006b,
		0x000020, 0x000061, 0x000020, 0x000057, 0x000065, 0x000062, 0x000020, 0x00006e,
		0x000079, 0x0000fa, 0x00006a, 0x000074, 0x00006f, 0x000074, 0x000074, 0x000061,
		0x000020, 0x0000f6, 0x000073, 0x000073, 0x00007a, 0x000065, 0x000073, 0x000020,
		0x00006c, 0x000065, 0x000068, 0x000065, 0x000074, 0x000151, 0x000073, 0x0000e9,
		0x000067, 0x000065, 0x000074, 0x002026, 0x000000 };

// Italian:  Sviluppare al massimo il potenziale del Web…
static const char k_testCase09Utf8Input[] =
	{ '\x49', '\x74', '\x61', '\x6c', '\x69', '\x61', '\x6e', '\x3a', '\x20', '\x20',
		'\x53', '\x76', '\x69', '\x6c', '\x75', '\x70', '\x70', '\x61', '\x72', '\x65',
		'\x20', '\x61', '\x6c', '\x20', '\x6d', '\x61', '\x73', '\x73', '\x69', '\x6d',
		'\x6f', '\x20', '\x69', '\x6c', '\x20', '\x70', '\x6f', '\x74', '\x65', '\x6e',
		'\x7a', '\x69', '\x61', '\x6c', '\x65', '\x20', '\x64', '\x65', '\x6c', '\x20',
		'\x57', '\x65', '\x62', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase09Utf16Input[] =
	{ 0x0049, 0x0074, 0x0061, 0x006c, 0x0069, 0x0061, 0x006e, 0x003a, 0x0020, 0x0020,
		0x0053, 0x0076, 0x0069, 0x006c, 0x0075, 0x0070, 0x0070, 0x0061, 0x0072, 0x0065,
		0x0020, 0x0061, 0x006c, 0x0020, 0x006d, 0x0061, 0x0073, 0x0073, 0x0069, 0x006d,
		0x006f, 0x0020, 0x0069, 0x006c, 0x0020, 0x0070, 0x006f, 0x0074, 0x0065, 0x006e,
		0x007a, 0x0069, 0x0061, 0x006c, 0x0065, 0x0020, 0x0064, 0x0065, 0x006c, 0x0020,
		0x0057, 0x0065, 0x0062, 0x2026, 0x0000 };
static const Utf32Char k_testCase09ExpectedResult[] =
	{ 0x000049, 0x000074, 0x000061, 0x00006c, 0x000069, 0x000061, 0x00006e, 0x00003a,
		0x000020, 0x000020, 0x000053, 0x000076, 0x000069, 0x00006c, 0x000075, 0x000070,
		0x000070, 0x000061, 0x000072, 0x000065, 0x000020, 0x000061, 0x00006c, 0x000020,
		0x00006d, 0x000061, 0x000073, 0x000073, 0x000069, 0x00006d, 0x00006f, 0x000020,
		0x000069, 0x00006c, 0x000020, 0x000070, 0x00006f, 0x000074, 0x000065, 0x00006e,
		0x00007a, 0x000069, 0x000061, 0x00006c, 0x000065, 0x000020, 0x000064, 0x000065,
		0x00006c, 0x000020, 0x000057, 0x000065, 0x000062, 0x002026, 0x000000 };

// Chinese:  引发网络的全部潜能…
static const char k_testCase10Utf8Input[] =
	{ '\x43', '\x68', '\x69', '\x6e', '\x65', '\x73', '\x65', '\x3a', '\x20', '\x20',
		'\xe5', '\xbc', '\x95', '\xe5', '\x8f', '\x91', '\xe7', '\xbd', '\x91', '\xe7',
		'\xbb', '\x9c', '\xe7', '\x9a', '\x84', '\xe5', '\x85', '\xa8', '\xe9', '\x83',
		'\xa8', '\xe6', '\xbd', '\x9c', '\xe8', '\x83', '\xbd', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase10Utf16Input[] =
	{ 0x0043, 0x0068, 0x0069, 0x006e, 0x0065, 0x0073, 0x0065, 0x003a, 0x0020, 0x0020,
		0x5f15, 0x53d1, 0x7f51, 0x7edc, 0x7684, 0x5168, 0x90e8, 0x6f5c, 0x80fd, 0x2026, 0x0000 };
static const Utf32Char k_testCase10ExpectedResult[] =
	{ 0x000043, 0x000068, 0x000069, 0x00006e, 0x000065, 0x000073, 0x000065, 0x00003a,
		0x000020, 0x000020, 0x005f15, 0x0053d1, 0x007f51, 0x007edc, 0x007684, 0x005168,
		0x0090e8, 0x006f5c, 0x0080fd, 0x002026, 0x000000 };

// Korean:  웹의 모든 잠재력을 이끌어 내기 위하여…
static const char k_testCase11Utf8Input[] =
	{ '\x4b', '\x6f', '\x72', '\x65', '\x61', '\x6e', '\x3a', '\x20', '\x20', '\xec',
		'\x9b', '\xb9', '\xec', '\x9d', '\x98', '\x20', '\xeb', '\xaa', '\xa8', '\xeb',
		'\x93', '\xa0', '\x20', '\xec', '\x9e', '\xa0', '\xec', '\x9e', '\xac', '\xeb',
		'\xa0', '\xa5', '\xec', '\x9d', '\x84', '\x20', '\xec', '\x9d', '\xb4', '\xeb',
		'\x81', '\x8c', '\xec', '\x96', '\xb4', '\x20', '\xeb', '\x82', '\xb4', '\xea',
		'\xb8', '\xb0', '\x20', '\xec', '\x9c', '\x84', '\xed', '\x95', '\x98', '\xec',
		'\x97', '\xac', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase11Utf16Input[] =
	{ 0x004b, 0x006f, 0x0072, 0x0065, 0x0061, 0x006e, 0x003a, 0x0020, 0x0020, 0xc6f9,
		0xc758, 0x0020, 0xbaa8, 0xb4e0, 0x0020, 0xc7a0, 0xc7ac, 0xb825, 0xc744, 0x0020,
		0xc774, 0xb04c, 0xc5b4, 0x0020, 0xb0b4, 0xae30, 0x0020, 0xc704, 0xd558, 0xc5ec,
		0x2026, 0x0000 };
static const Utf32Char k_testCase11ExpectedResult[] =
	{ 0x00004b, 0x00006f, 0x000072, 0x000065, 0x000061, 0x00006e, 0x00003a, 0x000020,
		0x000020, 0x00c6f9, 0x00c758, 0x000020, 0x00baa8, 0x00b4e0, 0x000020, 0x00c7a0,
		0x00c7ac, 0x00b825, 0x00c744, 0x000020, 0x00c774, 0x00b04c, 0x00c5b4, 0x000020,
		0x00b0b4, 0x00ae30, 0x000020, 0x00c704, 0x00d558, 0x00c5ec, 0x002026, 0x000000 };

// Portuguese:  Levando a Web em direcção ao seu potencial màximo…
static const char k_testCase12Utf8Input[] =
	{ '\x50', '\x6f', '\x72', '\x74', '\x75', '\x67', '\x75', '\x65', '\x73', '\x65',
		'\x3a', '\x20', '\x20', '\x4c', '\x65', '\x76', '\x61', '\x6e', '\x64', '\x6f',
		'\x20', '\x61', '\x20', '\x57', '\x65', '\x62', '\x20', '\x65', '\x6d', '\x20',
		'\x64', '\x69', '\x72', '\x65', '\x63', '\xc3', '\xa7', '\xc3', '\xa3', '\x6f',
		'\x20', '\x61', '\x6f', '\x20', '\x73', '\x65', '\x75', '\x20', '\x70', '\x6f',
		'\x74', '\x65', '\x6e', '\x63', '\x69', '\x61', '\x6c', '\x20', '\x6d', '\xc3',
		'\xa0', '\x78', '\x69', '\x6d', '\x6f', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase12Utf16Input[] =
	{ 0x0050, 0x006f, 0x0072, 0x0074, 0x0075, 0x0067, 0x0075, 0x0065, 0x0073, 0x0065,
		0x003a, 0x0020, 0x0020, 0x004c, 0x0065, 0x0076, 0x0061, 0x006e, 0x0064, 0x006f,
		0x0020, 0x0061, 0x0020, 0x0057, 0x0065, 0x0062, 0x0020, 0x0065, 0x006d, 0x0020,
		0x0064, 0x0069, 0x0072, 0x0065, 0x0063, 0x00e7, 0x00e3, 0x006f, 0x0020, 0x0061,
		0x006f, 0x0020, 0x0073, 0x0065, 0x0075, 0x0020, 0x0070, 0x006f, 0x0074, 0x0065,
		0x006e, 0x0063, 0x0069, 0x0061, 0x006c, 0x0020, 0x006d, 0x00e0, 0x0078, 0x0069,
		0x006d, 0x006f, 0x2026, 0x0000 };
static const Utf32Char k_testCase12ExpectedResult[] =
	{ 0x000050, 0x00006f, 0x000072, 0x000074, 0x000075, 0x000067, 0x000075, 0x000065,
		0x000073, 0x000065, 0x00003a, 0x000020, 0x000020, 0x00004c, 0x000065, 0x000076,
		0x000061, 0x00006e, 0x000064, 0x00006f, 0x000020, 0x000061, 0x000020, 0x000057,
		0x000065, 0x000062, 0x000020, 0x000065, 0x00006d, 0x000020, 0x000064, 0x000069,
		0x000072, 0x000065, 0x000063, 0x0000e7, 0x0000e3, 0x00006f, 0x000020, 0x000061,
		0x00006f, 0x000020, 0x000073, 0x000065, 0x000075, 0x000020, 0x000070, 0x00006f,
		0x000074, 0x000065, 0x00006e, 0x000063, 0x000069, 0x000061, 0x00006c, 0x000020,
		0x00006d, 0x0000e0, 0x000078, 0x000069, 0x00006d, 0x00006f, 0x002026, 0x000000 };

// Russian:  Pаскрывая весь потенциал Сети…
static const char k_testCase13Utf8Input[] =
	{ '\x52', '\x75', '\x73', '\x73', '\x69', '\x61', '\x6e', '\x3a', '\x20', '\x20',
		'\x50', '\xd0', '\xb0', '\xd1', '\x81', '\xd0', '\xba', '\xd1', '\x80', '\xd1',
		'\x8b', '\xd0', '\xb2', '\xd0', '\xb0', '\xd1', '\x8f', '\x20', '\xd0', '\xb2',
		'\xd0', '\xb5', '\xd1', '\x81', '\xd1', '\x8c', '\x20', '\xd0', '\xbf', '\xd0',
		'\xbe', '\xd1', '\x82', '\xd0', '\xb5', '\xd0', '\xbd', '\xd1', '\x86', '\xd0',
		'\xb8', '\xd0', '\xb0', '\xd0', '\xbb', '\x20', '\xd0', '\xa1', '\xd0', '\xb5',
		'\xd1', '\x82', '\xd0', '\xb8', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase13Utf16Input[] =
	{ 0x0052, 0x0075, 0x0073, 0x0073, 0x0069, 0x0061, 0x006e, 0x003a, 0x0020, 0x0020,
		0x0050, 0x0430, 0x0441, 0x043a, 0x0440, 0x044b, 0x0432, 0x0430, 0x044f, 0x0020,
		0x0432, 0x0435, 0x0441, 0x044c, 0x0020, 0x043f, 0x043e, 0x0442, 0x0435, 0x043d,
		0x0446, 0x0438, 0x0430, 0x043b, 0x0020, 0x0421, 0x0435, 0x0442, 0x0438, 0x2026, 0x0000 };
static const Utf32Char k_testCase13ExpectedResult[] =
	{ 0x000052, 0x000075, 0x000073, 0x000073, 0x000069, 0x000061, 0x00006e, 0x00003a,
		0x000020, 0x000020, 0x000050, 0x000430, 0x000441, 0x00043a, 0x000440, 0x00044b,
		0x000432, 0x000430, 0x00044f, 0x000020, 0x000432, 0x000435, 0x000441, 0x00044c,
		0x000020, 0x00043f, 0x00043e, 0x000442, 0x000435, 0x00043d, 0x000446, 0x000438,
		0x000430, 0x00043b, 0x000020, 0x000421, 0x000435, 0x000442, 0x000438, 0x002026, 0x000000 };

// Spanish:  Guiando el Web a su completo potencial…
static const char k_testCase14Utf8Input[] =
	{ '\x53', '\x70', '\x61', '\x6e', '\x69', '\x73', '\x68', '\x3a', '\x20', '\x20',
		'\x47', '\x75', '\x69', '\x61', '\x6e', '\x64', '\x6f', '\x20', '\x65', '\x6c',
		'\x20', '\x57', '\x65', '\x62', '\x20', '\x61', '\x20', '\x73', '\x75', '\x20',
		'\x63', '\x6f', '\x6d', '\x70', '\x6c', '\x65', '\x74', '\x6f', '\x20', '\x70',
		'\x6f', '\x74', '\x65', '\x6e', '\x63', '\x69', '\x61', '\x6c', '\xe2', '\x80',
		'\xa6', '\x00' };
static const Utf16Char k_testCase14Utf16Input[] =
	{ 0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0068, 0x003a, 0x0020, 0x0020,
		0x0047, 0x0075, 0x0069, 0x0061, 0x006e, 0x0064, 0x006f, 0x0020, 0x0065, 0x006c,
		0x0020, 0x0057, 0x0065, 0x0062, 0x0020, 0x0061, 0x0020, 0x0073, 0x0075, 0x0020,
		0x0063, 0x006f, 0x006d, 0x0070, 0x006c, 0x0065, 0x0074, 0x006f, 0x0020, 0x0070,
		0x006f, 0x0074, 0x0065, 0x006e, 0x0063, 0x0069, 0x0061, 0x006c, 0x2026, 0x0000 };
static const Utf32Char k_testCase14ExpectedResult[] =
	{ 0x000053, 0x000070, 0x000061, 0x00006e, 0x000069, 0x000073, 0x000068, 0x00003a,
		0x000020, 0x000020, 0x000047, 0x000075, 0x000069, 0x000061, 0x00006e, 0x000064,
		0x00006f, 0x000020, 0x000065, 0x00006c, 0x000020, 0x000057, 0x000065, 0x000062,
		0x000020, 0x000061, 0x000020, 0x000073, 0x000075, 0x000020, 0x000063, 0x00006f,
		0x00006d, 0x000070, 0x00006c, 0x000065, 0x000074, 0x00006f, 0x000020, 0x000070,
		0x00006f, 0x000074, 0x000065, 0x00006e, 0x000063, 0x000069, 0x000061, 0x00006c,
		0x002026, 0x000000 };

// Swedish:  Se till att Webben når sin fulla potential…
static const char k_testCase15Utf8Input[] =
	{ '\x53', '\x77', '\x65', '\x64', '\x69', '\x73', '\x68', '\x3a', '\x20', '\x20',
		'\x53', '\x65', '\x20', '\x74', '\x69', '\x6c', '\x6c', '\x20', '\x61', '\x74',
		'\x74', '\x20', '\x57', '\x65', '\x62', '\x62', '\x65', '\x6e', '\x20', '\x6e',
		'\xc3', '\xa5', '\x72', '\x20', '\x73', '\x69', '\x6e', '\x20', '\x66', '\x75',
		'\x6c', '\x6c', '\x61', '\x20', '\x70', '\x6f', '\x74', '\x65', '\x6e', '\x74',
		'\x69', '\x61', '\x6c', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase15Utf16Input[] =
	{ 0x0053, 0x0077, 0x0065, 0x0064, 0x0069, 0x0073, 0x0068, 0x003a, 0x0020, 0x0020,
		0x0053, 0x0065, 0x0020, 0x0074, 0x0069, 0x006c, 0x006c, 0x0020, 0x0061, 0x0074,
		0x0074, 0x0020, 0x0057, 0x0065, 0x0062, 0x0062, 0x0065, 0x006e, 0x0020, 0x006e,
		0x00e5, 0x0072, 0x0020, 0x0073, 0x0069, 0x006e, 0x0020, 0x0066, 0x0075, 0x006c,
		0x006c, 0x0061, 0x0020, 0x0070, 0x006f, 0x0074, 0x0065, 0x006e, 0x0074, 0x0069,
		0x0061, 0x006c, 0x2026, 0x0000 };
static const Utf32Char k_testCase15ExpectedResult[] =
	{ 0x000053, 0x000077, 0x000065, 0x000064, 0x000069, 0x000073, 0x000068, 0x00003a,
		0x000020, 0x000020, 0x000053, 0x000065, 0x000020, 0x000074, 0x000069, 0x00006c,
		0x00006c, 0x000020, 0x000061, 0x000074, 0x000074, 0x000020, 0x000057, 0x000065,
		0x000062, 0x000062, 0x000065, 0x00006e, 0x000020, 0x00006e, 0x0000e5, 0x000072,
		0x000020, 0x000073, 0x000069, 0x00006e, 0x000020, 0x000066, 0x000075, 0x00006c,
		0x00006c, 0x000061, 0x000020, 0x000070, 0x00006f, 0x000074, 0x000065, 0x00006e,
		0x000074, 0x000069, 0x000061, 0x00006c, 0x002026, 0x000000 };

// Finnish:  Ohjaamassa Webin kehittymistä täyteen mittaansa…
static const char k_testCase16Utf8Input[] =
	{ '\x46', '\x69', '\x6e', '\x6e', '\x69', '\x73', '\x68', '\x3a', '\x20', '\x20',
		'\x4f', '\x68', '\x6a', '\x61', '\x61', '\x6d', '\x61', '\x73', '\x73', '\x61',
		'\x20', '\x57', '\x65', '\x62', '\x69', '\x6e', '\x20', '\x6b', '\x65', '\x68',
		'\x69', '\x74', '\x74', '\x79', '\x6d', '\x69', '\x73', '\x74', '\xc3', '\xa4',
		'\x20', '\x74', '\xc3', '\xa4', '\x79', '\x74', '\x65', '\x65', '\x6e', '\x20',
		'\x6d', '\x69', '\x74', '\x74', '\x61', '\x61', '\x6e', '\x73', '\x61', '\xe2',
		'\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase16Utf16Input[] =
	{ 0x0046, 0x0069, 0x006e, 0x006e, 0x0069, 0x0073, 0x0068, 0x003a, 0x0020, 0x0020,
		0x004f, 0x0068, 0x006a, 0x0061, 0x0061, 0x006d, 0x0061, 0x0073, 0x0073, 0x0061,
		0x0020, 0x0057, 0x0065, 0x0062, 0x0069, 0x006e, 0x0020, 0x006b, 0x0065, 0x0068,
		0x0069, 0x0074, 0x0074, 0x0079, 0x006d, 0x0069, 0x0073, 0x0074, 0x00e4, 0x0020,
		0x0074, 0x00e4, 0x0079, 0x0074, 0x0065, 0x0065, 0x006e, 0x0020, 0x006d, 0x0069,
		0x0074, 0x0074, 0x0061, 0x0061, 0x006e, 0x0073, 0x0061, 0x2026, 0x0000 };
static const Utf32Char k_testCase16ExpectedResult[] =
	{ 0x000046, 0x000069, 0x00006e, 0x00006e, 0x000069, 0x000073, 0x000068, 0x00003a,
		0x000020, 0x000020, 0x00004f, 0x000068, 0x00006a, 0x000061, 0x000061, 0x00006d,
		0x000061, 0x000073, 0x000073, 0x000061, 0x000020, 0x000057, 0x000065, 0x000062,
		0x000069, 0x00006e, 0x000020, 0x00006b, 0x000065, 0x000068, 0x000069, 0x000074,
		0x000074, 0x000079, 0x00006d, 0x000069, 0x000073, 0x000074, 0x0000e4, 0x000020,
		0x000074, 0x0000e4, 0x000079, 0x000074, 0x000065, 0x000065, 0x00006e, 0x000020,
		0x00006d, 0x000069, 0x000074, 0x000074, 0x000061, 0x000061, 0x00006e, 0x000073,
		0x000061, 0x002026, 0x000000 };

// Hebrew:  להוביל את הרשת למיצוי הפוטנציאל שלה…
static const char k_testCase17Utf8Input[] =
	{ '\x48', '\x65', '\x62', '\x72', '\x65', '\x77', '\x3a', '\x20', '\x20', '\xd7',
		'\x9c', '\xd7', '\x94', '\xd7', '\x95', '\xd7', '\x91', '\xd7', '\x99', '\xd7',
		'\x9c', '\x20', '\xd7', '\x90', '\xd7', '\xaa', '\x20', '\xd7', '\x94', '\xd7',
		'\xa8', '\xd7', '\xa9', '\xd7', '\xaa', '\x20', '\xd7', '\x9c', '\xd7', '\x9e',
		'\xd7', '\x99', '\xd7', '\xa6', '\xd7', '\x95', '\xd7', '\x99', '\x20', '\xd7',
		'\x94', '\xd7', '\xa4', '\xd7', '\x95', '\xd7', '\x98', '\xd7', '\xa0', '\xd7',
		'\xa6', '\xd7', '\x99', '\xd7', '\x90', '\xd7', '\x9c', '\x20', '\xd7', '\xa9',
		'\xd7', '\x9c', '\xd7', '\x94', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase17Utf16Input[] =
	{ 0x0048, 0x0065, 0x0062, 0x0072, 0x0065, 0x0077, 0x003a, 0x0020, 0x0020, 0x05dc,
		0x05d4, 0x05d5, 0x05d1, 0x05d9, 0x05dc, 0x0020, 0x05d0, 0x05ea, 0x0020, 0x05d4,
		0x05e8, 0x05e9, 0x05ea, 0x0020, 0x05dc, 0x05de, 0x05d9, 0x05e6, 0x05d5, 0x05d9,
		0x0020, 0x05d4, 0x05e4, 0x05d5, 0x05d8, 0x05e0, 0x05e6, 0x05d9, 0x05d0, 0x05dc,
		0x0020, 0x05e9, 0x05dc, 0x05d4, 0x2026, 0x0000 };
static const Utf32Char k_testCase17ExpectedResult[] =
	{ 0x000048, 0x000065, 0x000062, 0x000072, 0x000065, 0x000077, 0x00003a, 0x000020,
		0x000020, 0x0005dc, 0x0005d4, 0x0005d5, 0x0005d1, 0x0005d9, 0x0005dc, 0x000020,
		0x0005d0, 0x0005ea, 0x000020, 0x0005d4, 0x0005e8, 0x0005e9, 0x0005ea, 0x000020,
		0x0005dc, 0x0005de, 0x0005d9, 0x0005e6, 0x0005d5, 0x0005d9, 0x000020, 0x0005d4,
		0x0005e4, 0x0005d5, 0x0005d8, 0x0005e0, 0x0005e6, 0x0005d9, 0x0005d0, 0x0005dc,
		0x000020, 0x0005e9, 0x0005dc, 0x0005d4, 0x002026, 0x000000 };

// Arabic:  لإيصال الشبكة المعلوماتية إلىأقصى إمكانياتها…
static const char k_testCase18Utf8Input[] =
	{ '\x41', '\x72', '\x61', '\x62', '\x69', '\x63', '\x3a', '\x20', '\x20', '\xd9',
		'\x84', '\xd8', '\xa5', '\xd9', '\x8a', '\xd8', '\xb5', '\xd8', '\xa7', '\xd9',
		'\x84', '\x20', '\xd8', '\xa7', '\xd9', '\x84', '\xd8', '\xb4', '\xd8', '\xa8',
		'\xd9', '\x83', '\xd8', '\xa9', '\x20', '\xd8', '\xa7', '\xd9', '\x84', '\xd9',
		'\x85', '\xd8', '\xb9', '\xd9', '\x84', '\xd9', '\x88', '\xd9', '\x85', '\xd8',
		'\xa7', '\xd8', '\xaa', '\xd9', '\x8a', '\xd8', '\xa9', '\x20', '\xd8', '\xa5',
		'\xd9', '\x84', '\xd9', '\x89', '\xd8', '\xa3', '\xd9', '\x82', '\xd8', '\xb5',
		'\xd9', '\x89', '\x20', '\xd8', '\xa5', '\xd9', '\x85', '\xd9', '\x83', '\xd8',
		'\xa7', '\xd9', '\x86', '\xd9', '\x8a', '\xd8', '\xa7', '\xd8', '\xaa', '\xd9',
		'\x87', '\xd8', '\xa7', '\xe2', '\x80', '\xa6', '\x00' };
static const Utf16Char k_testCase18Utf16Input[] =
	{ 0x0041, 0x0072, 0x0061, 0x0062, 0x0069, 0x0063, 0x003a, 0x0020, 0x0020, 0x0644,
		0x0625, 0x064a, 0x0635, 0x0627, 0x0644, 0x0020, 0x0627, 0x0644, 0x0634, 0x0628,
		0x0643, 0x0629, 0x0020, 0x0627, 0x0644, 0x0645, 0x0639, 0x0644, 0x0648, 0x0645,
		0x0627, 0x062a, 0x064a, 0x0629, 0x0020, 0x0625, 0x0644, 0x0649, 0x0623, 0x0642,
		0x0635, 0x0649, 0x0020, 0x0625, 0x0645, 0x0643, 0x0627, 0x0646, 0x064a, 0x0627,
		0x062a, 0x0647, 0x0627, 0x2026, 0x0000 };
static const Utf32Char k_testCase18ExpectedResult[] =
	{ 0x000041, 0x000072, 0x000061, 0x000062, 0x000069, 0x000063, 0x00003a, 0x000020,
		0x000020, 0x000644, 0x000625, 0x00064a, 0x000635, 0x000627, 0x000644, 0x000020,
		0x000627, 0x000644, 0x000634, 0x000628, 0x000643, 0x000629, 0x000020, 0x000627,
		0x000644, 0x000645, 0x000639, 0x000644, 0x000648, 0x000645, 0x000627, 0x00062a,
		0x00064a, 0x000629, 0x000020, 0x000625, 0x000644, 0x000649, 0x000623, 0x000642,
		0x000635, 0x000649, 0x000020, 0x000625, 0x000645, 0x000643, 0x000627, 0x000646,
		0x00064a, 0x000627, 0x00062a, 0x000647, 0x000627, 0x002026, 0x000000 };

// Chinese:  引發網絡的全部潛能⋮
static const char k_testCase19Utf8Input[] =
	{ '\x43', '\x68', '\x69', '\x6e', '\x65', '\x73', '\x65', '\x3a', '\x20', '\x20',
		'\xe5', '\xbc', '\x95', '\xe7', '\x99', '\xbc', '\xe7', '\xb6', '\xb2', '\xe7',
		'\xb5', '\xa1', '\xe7', '\x9a', '\x84', '\xe5', '\x85', '\xa8', '\xe9', '\x83',
		'\xa8', '\xe6', '\xbd', '\x9b', '\xe8', '\x83', '\xbd', '\xe2', '\x8b', '\xae', '\x00' };
static const Utf16Char k_testCase19Utf16Input[] =
	{ 0x0043, 0x0068, 0x0069, 0x006e, 0x0065, 0x0073, 0x0065, 0x003a, 0x0020, 0x0020,
		0x5f15, 0x767c, 0x7db2, 0x7d61, 0x7684, 0x5168, 0x90e8, 0x6f5b, 0x80fd, 0x22ee, 0x0000 };
static const Utf32Char k_testCase19ExpectedResult[] =
	{ 0x000043, 0x000068, 0x000069, 0x00006e, 0x000065, 0x000073, 0x000065, 0x00003a,
		0x000020, 0x000020, 0x005f15, 0x00767c, 0x007db2, 0x007d61, 0x007684, 0x005168,
		0x0090e8, 0x006f5b, 0x0080fd, 0x0022ee, 0x000000 };

// Japanese:  Webの可能性を最大限に導き出すために⋮
static const char k_testCase20Utf8Input[] =
	{ '\x4a', '\x61', '\x70', '\x61', '\x6e', '\x65', '\x73', '\x65', '\x3a', '\x20',
		'\x20', '\x57', '\x65', '\x62', '\xe3', '\x81', '\xae', '\xe5', '\x8f', '\xaf',
		'\xe8', '\x83', '\xbd', '\xe6', '\x80', '\xa7', '\xe3', '\x82', '\x92', '\xe6',
		'\x9c', '\x80', '\xe5', '\xa4', '\xa7', '\xe9', '\x99', '\x90', '\xe3', '\x81',
		'\xab', '\xe5', '\xb0', '\x8e', '\xe3', '\x81', '\x8d', '\xe5', '\x87', '\xba',
		'\xe3', '\x81', '\x99', '\xe3', '\x81', '\x9f', '\xe3', '\x82', '\x81', '\xe3',
		'\x81', '\xab', '\xe2', '\x8b', '\xae', '\x00' };
static const Utf16Char k_testCase20Utf16Input[] =
	{ 0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0065, 0x0073, 0x0065, 0x003a, 0x0020,
		0x0020, 0x0057, 0x0065, 0x0062, 0x306e, 0x53ef, 0x80fd, 0x6027, 0x3092, 0x6700,
		0x5927, 0x9650, 0x306b, 0x5c0e, 0x304d, 0x51fa, 0x3059, 0x305f, 0x3081, 0x306b,
		0x22ee, 0x0000 };
static const Utf32Char k_testCase20ExpectedResult[] =
	{ 0x00004a, 0x000061, 0x000070, 0x000061, 0x00006e, 0x000065, 0x000073, 0x000065,
		0x00003a, 0x000020, 0x000020, 0x000057, 0x000065, 0x000062, 0x00306e, 0x0053ef,
		0x0080fd, 0x006027, 0x003092, 0x006700, 0x005927, 0x009650, 0x00306b, 0x005c0e,
		0x00304d, 0x0051fa, 0x003059, 0x00305f, 0x003081, 0x00306b, 0x0022ee, 0x000000 };

static const TestCase k_testData[] =
	{
		{ k_testCase00Utf8Input, k_testCase00Utf16Input, k_testCase00ExpectedResult },
		{ k_testCase01Utf8Input, k_testCase01Utf16Input, k_testCase01ExpectedResult },
		{ k_testCase02Utf8Input, k_testCase02Utf16Input, k_testCase02ExpectedResult },
		{ k_testCase03Utf8Input, k_testCase03Utf16Input, k_testCase03ExpectedResult },
		{ k_testCase04Utf8Input, k_testCase04Utf16Input, k_testCase04ExpectedResult },
		{ k_testCase05Utf8Input, k_testCase05Utf16Input, k_testCase05ExpectedResult },
		{ k_testCase06Utf8Input, k_testCase06Utf16Input, k_testCase06ExpectedResult },
		{ k_testCase07Utf8Input, k_testCase07Utf16Input, k_testCase07ExpectedResult },
		{ k_testCase08Utf8Input, k_testCase08Utf16Input, k_testCase08ExpectedResult },
		{ k_testCase09Utf8Input, k_testCase09Utf16Input, k_testCase09ExpectedResult },
		{ k_testCase10Utf8Input, k_testCase10Utf16Input, k_testCase10ExpectedResult },
		{ k_testCase11Utf8Input, k_testCase11Utf16Input, k_testCase11ExpectedResult },
		{ k_testCase12Utf8Input, k_testCase12Utf16Input, k_testCase12ExpectedResult },
		{ k_testCase13Utf8Input, k_testCase13Utf16Input, k_testCase13ExpectedResult },
		{ k_testCase14Utf8Input, k_testCase14Utf16Input, k_testCase14ExpectedResult },
		{ k_testCase15Utf8Input, k_testCase15Utf16Input, k_testCase15ExpectedResult },
		{ k_testCase16Utf8Input, k_testCase16Utf16Input, k_testCase16ExpectedResult },
		{ k_testCase17Utf8Input, k_testCase17Utf16Input, k_testCase17ExpectedResult },
		{ k_testCase18Utf8Input, k_testCase18Utf16Input, k_testCase18ExpectedResult },
		{ k_testCase19Utf8Input, k_testCase19Utf16Input, k_testCase19ExpectedResult },
		{ k_testCase20Utf8Input, k_testCase20Utf16Input, k_testCase20ExpectedResult },
	};

/////////////// Generated by UnicodeTestCaseGen.cpp -- End ///////////////

// Malformed UTF-8 input:
static const char k_testCaseOfBadInput[] =
	{ '\x5a', '\x81', '\xc3', '\x7f', '\xe0', '\x9f', '\x81', '\xe0', '\xa1', '\x7f', '\x00' };

BOOST_AUTO_TEST_SUITE(UnicodeIteratorTestSuite)

template <typename t_char, typename t_FwdIter>
void goodInputTestHelper(UnicodeIterator<t_char, t_FwdIter> iter, UnicodeIterator<t_char, t_FwdIter> end,
	const uint32* pExpectedResult, bool strictConversion)
{
	BOOST_REQUIRE((strictConversion && iter.canThrow()) || (!strictConversion && !iter.canThrow()));
	BOOST_REQUIRE(!iter.errorOccurred() && !end.errorOccurred());
	for (; iter != end; ++iter, ++pExpectedResult)
	{
		BOOST_REQUIRE_MESSAGE(
			*pExpectedResult != 0,
			"Reached the end of the expected result before consuming all of the input");
		BOOST_REQUIRE_MESSAGE(
			*iter == *pExpectedResult,
			"UnicodeIterator output does not match the expected result");
	}
	BOOST_REQUIRE_MESSAGE(
		*pExpectedResult == 0,
		"UnicodeIterator reached the end of the input with characters left over in the expected result");
}

static const char* skipBOM(const char* pStr)
{
	bool hasBOM = (pStr != nullptr && pStr[0] == '\xef' && pStr[1] == '\xbb' && pStr[2] == '\xbf');
	return pStr + (hasBOM ? 3 : 0);
}

static const Utf16Char* skipBOM(const Utf16Char* pStr)
{
	bool hasBOM = (pStr != nullptr && (pStr[0] == 0xfeffu || pStr[0] == 0xfffeu));
	return pStr + (hasBOM ? 1 : 0);
}

BOOST_DATA_TEST_CASE(
	testIteratorOnGoodInput,
	bdata::make(k_testData),
	tc)
{
	const char* pStr8 = tc.m_pUtf8Input;
	goodInputTestHelper(
		UnicodeIteratorFactory<char>::begin(pStr8),
		UnicodeIteratorFactory<char>::end(pStr8),
		tc.m_pExpectedResult, true);
	goodInputTestHelper(
		UnicodeIteratorFactory<char>::begin(pStr8, nothrow),
		UnicodeIteratorFactory<char>::end(pStr8),
		tc.m_pExpectedResult, false);

	const Utf16Char* pStr16 = tc.m_pUtf16Input;
	goodInputTestHelper(
		UnicodeIteratorFactory<Utf16Char>::begin(pStr16),
		UnicodeIteratorFactory<Utf16Char>::end(pStr16),
		tc.m_pExpectedResult, true);
	goodInputTestHelper(
		UnicodeIteratorFactory<Utf16Char>::begin(pStr16, nothrow),
		UnicodeIteratorFactory<Utf16Char>::end(pStr16),
		tc.m_pExpectedResult, false);

	const string str8(pStr8);
	goodInputTestHelper(
		UnicodeIteratorFactory<char>::begin(str8),
		UnicodeIteratorFactory<char>::end(str8),
		tc.m_pExpectedResult, true);
	goodInputTestHelper(
		UnicodeIteratorFactory<char>::begin(str8, nothrow),
		UnicodeIteratorFactory<char>::end(str8),
		tc.m_pExpectedResult, false);

	const Utf16String str16(pStr16);
	goodInputTestHelper(
		UnicodeIteratorFactory<Utf16Char>::begin(str16),
		UnicodeIteratorFactory<Utf16Char>::end(str16),
		tc.m_pExpectedResult, true);
	goodInputTestHelper(
		UnicodeIteratorFactory<Utf16Char>::begin(str16, nothrow),
		UnicodeIteratorFactory<Utf16Char>::end(str16),
		tc.m_pExpectedResult, false);

	// Try a list to expose any assumptions that are dependant upon random access iterators:

	list<char> inputLst8(pStr8, pStr8 + char_traits<char>::length(pStr8));
	goodInputTestHelper(
		UnicodeIterator<char, list<char>::const_iterator>::begin(begin(inputLst8), end(inputLst8)),
		UnicodeIterator<char, list<char>::const_iterator>::end(end(inputLst8)),
		tc.m_pExpectedResult, true);
	goodInputTestHelper(
		UnicodeIterator<char, list<char>::const_iterator>::begin(begin(inputLst8), end(inputLst8), nothrow),
		UnicodeIterator<char, list<char>::const_iterator>::end(end(inputLst8)),
		tc.m_pExpectedResult, false);

	list<Utf16Char> inputLst16(pStr16, pStr16 + char_traits<Utf16Char>::length(pStr16));
	goodInputTestHelper(
		UnicodeIterator<Utf16Char, list<Utf16Char>::const_iterator>::begin(begin(inputLst16), end(inputLst16)),
		UnicodeIterator<Utf16Char, list<Utf16Char>::const_iterator>::end(end(inputLst16)),
		tc.m_pExpectedResult, true);
	goodInputTestHelper(
		UnicodeIterator<Utf16Char, list<Utf16Char>::const_iterator>::begin(begin(inputLst16), end(inputLst16), nothrow),
		UnicodeIterator<Utf16Char, list<Utf16Char>::const_iterator>::end(end(inputLst16)),
		tc.m_pExpectedResult, false);

	// Tests going from UTF-32 to UTF-8 and UTF-16:

	const Utf32Char* pUtf32Begin = tc.m_pExpectedResult;
	const Utf32Char* pUtf32End = pUtf32Begin + char_traits<Utf32Char>::length(pUtf32Begin);
	string utf8Result = convertUtf32ToUtf8(pUtf32Begin, pUtf32End, true);
	BOOST_CHECK(utf8Result == skipBOM(tc.m_pUtf8Input));
	utf8Result = convertUtf32ToUtf8(pUtf32Begin, pUtf32End, false);
	BOOST_CHECK(utf8Result == skipBOM(tc.m_pUtf8Input));

	Utf16String utf16Result = convertUtf32ToUtf16(pUtf32Begin, pUtf32End, true);
	BOOST_CHECK(utf16Result == skipBOM(tc.m_pUtf16Input));
	utf16Result = convertUtf32ToUtf16(pUtf32Begin, pUtf32End, false);
	BOOST_CHECK(utf16Result == skipBOM(tc.m_pUtf16Input));

	// Tests going from UTF-16 to UTF-8:

	utf8Result = convertToUtf8(tc.m_pUtf16Input, true);
	BOOST_CHECK(utf8Result == skipBOM(tc.m_pUtf8Input));
	utf8Result = convertToUtf8(tc.m_pUtf16Input, false);
	BOOST_CHECK(utf8Result == skipBOM(tc.m_pUtf8Input));

	// Tests going from UTF-8 to UTF-16:

	utf16Result = convertToUtf16(tc.m_pUtf8Input, true);
	BOOST_CHECK(utf16Result == skipBOM(tc.m_pUtf16Input));
	utf16Result = convertToUtf16(tc.m_pUtf8Input, false);
	BOOST_CHECK(utf16Result == skipBOM(tc.m_pUtf16Input));
}

template <typename t_FwdIter>
void badInputTestHelper(const t_FwdIter& beginOfInput, const t_FwdIter& endOfInput)
{
	{
		UnicodeIterator<char, t_FwdIter> iter = UnicodeIterator<char, t_FwdIter>::begin(beginOfInput, endOfInput);
		UnicodeIterator<char, t_FwdIter> end = UnicodeIterator<char, t_FwdIter>::end(endOfInput);
		BOOST_CHECK(iter.canThrow() && end.canThrow());
		BOOST_CHECK(!iter.errorOccurred() && !end.errorOccurred());
		BOOST_CHECK(*iter == static_cast<uint8>(k_testCaseOfBadInput[0]));

		BOOST_CHECK_THROW(++iter, UnicodeException);
	}

	{
		UnicodeIterator<char, t_FwdIter> iter = UnicodeIterator<char, t_FwdIter>::begin(beginOfInput, endOfInput, nothrow);
		UnicodeIterator<char, t_FwdIter> end = UnicodeIterator<char, t_FwdIter>::end(endOfInput);
		BOOST_CHECK(!iter.canThrow());
		BOOST_CHECK(!iter.errorOccurred() && !end.errorOccurred());
		BOOST_CHECK(*iter == static_cast<uint8>(k_testCaseOfBadInput[0]));

		const uint32 k_repChar = UnicodeIterator<char, t_FwdIter>::k_replacementChar;

		BOOST_CHECK_NO_THROW(++iter);
		BOOST_CHECK(*iter == k_repChar);
		BOOST_CHECK(iter.errorOccurred());
		BOOST_CHECK(strlen(iter.errorMsg()) > 0);
		BOOST_CHECK_NO_THROW(iter.clearError());
		BOOST_CHECK(!iter.errorOccurred());

		BOOST_CHECK_NO_THROW(++iter);
		BOOST_CHECK(*iter == k_repChar);
		BOOST_CHECK(iter.errorOccurred());
		BOOST_CHECK(strlen(iter.errorMsg()) > 0);
		BOOST_CHECK_NO_THROW(iter.clearError());
		BOOST_CHECK(!iter.errorOccurred());

		BOOST_CHECK_NO_THROW(++iter);
		BOOST_CHECK(*iter == k_repChar);
		BOOST_CHECK(iter.errorOccurred());
		BOOST_CHECK(strlen(iter.errorMsg()) > 0);
		BOOST_CHECK_NO_THROW(iter.clearError());
		BOOST_CHECK(!iter.errorOccurred());

		BOOST_CHECK_NO_THROW(++iter);
		BOOST_CHECK(*iter == k_repChar);
		BOOST_CHECK(iter.errorOccurred());
		BOOST_CHECK(strlen(iter.errorMsg()) > 0);
		BOOST_CHECK_NO_THROW(iter.clearError());
		BOOST_CHECK(!iter.errorOccurred());

		BOOST_CHECK(++iter == end);
		BOOST_CHECK(++iter == end);
	}
}

BOOST_AUTO_TEST_CASE(testIteratorOnBadInput)
{
	const char* pBegin = k_testCaseOfBadInput;
	const char* pEnd = pBegin + strlen(pBegin);
	badInputTestHelper(pBegin, pEnd);

	const string inputStr(k_testCaseOfBadInput);
	badInputTestHelper(begin(inputStr), end(inputStr));

	// Try a list to expose any assumptions that are inconsistent with forward iterators:
	list<char> inputLst(pBegin, pEnd);
	badInputTestHelper(begin(inputLst), end(inputLst));
	badInputTestHelper(begin(inputLst), end(inputLst));
}

BOOST_AUTO_TEST_SUITE_END()
